package com.example.performance.jol.official;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 * @author Aleksey Shipilev
 */
@SuppressWarnings({"java:S101", "java:S106", "java:S2094", "SynchronizationOnLocalVariableOrMethodParameter"})
public class JOLSample_12_BiasedLocking {

    /*
     * This is a dive into the mark word.
     *
     * Among other things, mark words store locking information.
     * We can clearly see how the mark word contents change when
     * we acquire the lock, and subsequently release it.
     *
     * In this example, we demonstrate biased locking.
     * Every Java object is potentially a target for synchronization.
     * Most of the time, the object is ever locked by a single thread.
     * In this case, we can "bias" the object to that single thread,
     * and make the synchronization on it very cheap.
     *
     * To demonstrate this, we print the object internals before/during/after
     * lock acquisition. You can notice that mark word changes from
     * "biasable" to "biased". The mark word is left the same after
     * unlock: the object is now biased towards the thread.
     *
     * Prior to JDK 9, biased locking is only enabled after 5 seconds
     * after the VM startup. Therefore, the test is best run with
     * -XX:BiasedLockingStartupDelay=0 on JDK 8 and lower.
     * JDK 15 -- JDK16,
     * biased locking is disabled by default, and this tests needs
     * -XX:+UseBiasedLocking.
     * From JDK 17, biased locking is disabled permanently. -XX:+UseBiasedLocking won't work
     */

    public static void main(String[] args) {
        System.out.println(VM.current().details());

        final A a = new A();

        ClassLayout layout = ClassLayout.parseInstance(a);

        System.out.println("**** Fresh object");
        System.out.println(layout.toPrintable());

        synchronized (a) {
            System.out.println("**** With the lock");
            System.out.println(layout.toPrintable());
        }

        System.out.println("**** After the lock");
        System.out.println(layout.toPrintable());
    }

    private static class A {
        // no fields
    }

}
